package JUC;

import java.util.LinkedList;
import java.util.List;

// 手写线程池
public class SimpleThreadPool {

    // 存储线程池中的任务队列
    private final List<Runnable> taskQueue = new LinkedList<>();
    // 线程池大小
    private final int nThreads;
    // 工作线程数组
    private final Worker[] workers;
    // 线程池是否正在运行
    private volatile boolean isRunning = true;

    /**
     * 构造一个指定大小的线程池
     * @param nThreads 线程池的大小
     */
    public SimpleThreadPool(int nThreads) {
        this.nThreads = nThreads;
        this.workers = new Worker[nThreads];
        for (int i = 0; i < nThreads; i++) {
            workers[i] = new Worker();
            workers[i].start(); // 启动工作线程
        }
    }

    /**
     * 提交任务到线程池
     * @param task 要提交的任务，实现Runnable接口
     */
    public void submit(Runnable task) {
        synchronized (taskQueue) {
            taskQueue.add(task);
            taskQueue.notify(); // 唤醒等待的任务执行者
        }
    }

    /**
     * 关闭线程池
     */
    public void shutdown() {
        isRunning = false;
        synchronized (taskQueue) {
            taskQueue.notifyAll(); // 唤醒所有可能在等待的任务执行者
        }
    }

    /**
     * 内部类：工作线程
     */
    private class Worker extends Thread {
        @Override
        public void run() {
            Runnable task;
            while (isRunning) {
                synchronized (taskQueue) {
                    while (isRunning && taskQueue.isEmpty()) {
                        try {
                            taskQueue.wait(); // 如果没有任务，则等待
                        } catch (InterruptedException e) {
                            // 捕获异常，保持循环
                        }
                    }
                    if (!taskQueue.isEmpty()) {
                        task = taskQueue.remove(0); // 获取并移除第一个任务
                    } else {
                        continue;
                    }
                }
                try {
                    task.run(); // 执行任务
                } catch (RuntimeException e) {
                    // 处理任务执行期间可能出现的异常
                }
            }
        }
    }

    /**
     * 程序入口
     * @param args 命令行参数
     * @throws InterruptedException 当线程被中断时抛出
     */
    public static void main(String[] args) throws InterruptedException {
        SimpleThreadPool pool = new SimpleThreadPool(2); // 创建包含2个工作线程的线程池

        // 提交一些任务
        for (int i = 1; i <= 5; i++) {
            final int taskId = i;
            pool.submit(() -> {
                System.out.println(Thread.currentThread().getName() + " 正在处理任务 " + taskId);
                try {
                    Thread.sleep(1000); // 模拟任务处理时间
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("任务 " + taskId + " 完成");
            });
        }

        // 给点时间让所有任务开始执行
        Thread.sleep(3000);

        // 关闭线程池
        pool.shutdown();
    }
}
